package com.csx.micrometer.invoke.core.outbound.loadbalance;

import com.csx.micrometer.common.util.MetricsUtil;
import com.csx.micrometer.invoke.constant.InvokeMetricsConstant;
import com.csx.micrometer.invoke.context.resttemplate.MicrometerRestTemplateRequest;
import com.csx.micrometer.invoke.context.resttemplate.MicrometerRestTemplateResponse;
import com.csx.micrometer.invoke.custom.TagsCustom;
import io.micrometer.core.instrument.Tags;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.cloud.client.loadbalancer.LoadBalancerClient;
import org.springframework.cloud.client.loadbalancer.LoadBalancerInterceptor;
import org.springframework.cloud.client.loadbalancer.LoadBalancerRequestFactory;
import org.springframework.http.HttpRequest;
import org.springframework.http.client.ClientHttpRequestExecution;
import org.springframework.http.client.ClientHttpResponse;

import java.io.IOException;
import java.util.Collections;
import java.util.List;

/**
 * TODO 需要测试这个拦截与restTemplate的拦截器是否在restTemplate发起基于服务名的外调时共用
 * @author cuisongxu
 * @date 2022/12/3 23:02
 */
public class MicrometerLoadBalancerOutboundInterceptor extends LoadBalancerInterceptor {

    private Logger logger = LoggerFactory.getLogger(MicrometerLoadBalancerOutboundInterceptor.class);

    private final List<TagsCustom> tagsCustoms;

    private LoadBalancerClient loadBalancerClient;

    private LoadBalancerRequestFactory loadBalancerRequestFactory;


    public MicrometerLoadBalancerOutboundInterceptor(LoadBalancerClient loadBalancer, LoadBalancerRequestFactory requestFactory, List<TagsCustom> tagsCustoms) {
        super(loadBalancer, requestFactory);
        this.loadBalancerClient = loadBalancer;
        this.loadBalancerRequestFactory = requestFactory;
        this.tagsCustoms = tagsCustoms;
    }

    @Override
    public ClientHttpResponse intercept(HttpRequest request, byte[] body, ClientHttpRequestExecution execution) throws IOException {

        ClientHttpResponse response = null;
        // 自定义tags
        Tags tags = Tags.of(Collections.emptyList());
        for (TagsCustom tagsCustom : tagsCustoms) {
            tags = tagsCustom.customTags(new MicrometerRestTemplateRequest(request), new MicrometerRestTemplateResponse(response), tags);
        }
        logger.info("all tags custom result: " + tags.toString());
        try {
            long start = System.currentTimeMillis();
            response = execution.execute(request, body);
            long end = System.currentTimeMillis();
            long responseMillis = end - start;

            // TODO 需要讨论调用耗时是只统计成功的还是 成功失败都统计
            MetricsUtil.record(InvokeMetricsConstant.INVOKE_RESPONSE_MILLIS, responseMillis, tags);
            MetricsUtil.counter(InvokeMetricsConstant.INVOKE_SUCCESS_TOTAL, tags).increment();
        }catch (Exception e) {
            // 统计异常状态指标
            MetricsUtil.counter(InvokeMetricsConstant.INVOKE_FAIL_TOTAL, tags).increment();
        }finally {
            MetricsUtil.counter(InvokeMetricsConstant.INVOKE_TOTAL, tags).increment();
        }
        return response;
    }
}
